/**
 * @file sysfont16.c
 * @brief
 *
 * @version Fixed
 * @author yemit
 * @date 2012-06-17
 */
#include <sys/ioctl.h>
#include <stdint.h>
#include "flash.h"
#include <key.h>
#include "resource.h"
#include "config.h"

#define FONT_COLOR 	0x0
#define BLACKGROUND 	0x1f1f

extern part_t * res_part;
extern res_entry_t sys_hzk;
extern res_entry_t sys_asc;
extern int lcd_fd;
extern lcd_info_t info;

#ifdef CONFIG_PRINTER_FONT
extern res_entry_t prn_hzk;
extern res_entry_t prn_asc;
#endif

extern void _lcd_disp_img(uint32_t x, uint32_t y,
                uint32_t w, uint32_t h, uint8_t * img);

static inline int read_sys_hzk(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + sys_hzk.offset, buf, len);
}

static inline int read_sys_asc(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + sys_asc.offset, buf, len);
}

#ifdef CONFIG_PRINTER_FONT
static inline int read_prn_hzk(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + prn_hzk.offset, buf, len);
}

static inline int read_prn_asc(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + prn_asc.offset, buf, len);
}
#endif

void hzk16(int x,int y,char *s)
{
	char* buffer = s;
	register i,j,k;
	for(i=0;i<16;i++)
		for(j=0;j<2;j++)
			for(k=0;k<8;k++)
				if(((buffer[i*2+j]>>(7-k))&0x1)!=NULL)
				{
					_lcd_put_pixel(x+8*j+k,y+i,FONT_COLOR);
				}else
					_lcd_put_pixel(x+8*j+k,y+i,BLACKGROUND);	

	   lcd_block_t blk;
	   blk.x = x;
	   blk.y = y;
           blk.w = 16;
	   blk.h = 16;
	   ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);

	   
}

 void ASC16(int x,int y,unsigned char* buf)
{
	int pos,t,i,j;
	unsigned char temp;

	for(i=0;i<16;i++) 
		for(j=0;j<8;j++) 
			if(((buf[i]>>(7-j))&0x1)!=NULL) 
				_lcd_put_pixel(j+x,i+y,FONT_COLOR);
			else
				_lcd_put_pixel(j+x,i+y,BLACKGROUND);

#ifdef CONFIG_SECURITY_PCI	
	 lcd_block_t blk;
	   blk.x = x;
	   blk.y = y;
       blk.w = 8;
	   blk.h = 16;
	   ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);			
#endif		
}


void lcd_disp_string(uint32_t x, uint32_t y, char * string)
{
        char *s = string;
        uint8_t font_buf[32];
        lcd_block_t blk;

        if (x >= info.width || y > info.height - 16 || !string) return;

        blk.x = 0;
        blk.w = info.width;
        blk.y = y;
        while (*s) {
                if (*s & 0x80) {
                        if (x > info.width - 16) {
                                x = 0;
                                y += 16;
                                if (y > info.height) break;
                        }
                        read_sys_hzk((94 * (*s - 0xa1) + (*(s + 1) - 0xa1)) * 32,
                                        font_buf, 32);
			hzk16(x, y,font_buf);
                       x += 16;
                        s += 2;
                }
                else {
                        if (*s == '\n') {
                                x = 0;
                                y += 16;
                                if (y > info.height) break;
				 s ++;
                                continue;
                        }
                        else if (*s == '\r') {
                                x = 0;
                                 s ++;
                                continue;
                        }
                        read_sys_asc((*s) * 16, font_buf, 16);

			ASC16(x,y,font_buf);
                        x += 8;
                        s ++;
                }
        }
        if (y > info.height) y -= 16;
        blk.h = y - blk.y + 16;
        ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);
}

int get_ascii_str(uint32_t x, uint32_t y, char * buf, uint32_t minlen,
                uint32_t maxlen, uint32_t secs, char show)
{
        uint8_t font_[17], font_ept[17], font_buf[17];
        int key, count = 0;
        lcd_block_t blk;

        blk.w = maxlen * 8;
        if (buf == NULL) return -1;
        if (y > info.height - 16) return -1;
        if (x > info.width - blk.w) return -1;
        if (maxlen < minlen) return -1;
        if (maxlen == 0) return 0;

        read_sys_asc('_' * 16, font_, 16);
        read_sys_asc(' ' * 16, font_ept, 16);
        if (show != 0)
                read_sys_asc(show * 16, font_buf, 16);
		
        blk.x = x;
        blk.y = y;
        blk.h = 16;
		timeouts_start( 0 );
        while (1) {
                ASC16(x, y, font_);
                ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);
				if( secs != 0 && timeouts_test( secs )){ 
					memset( buf, 0, count );		//clear sensitive data
					return -1;
                }
				
                key = kb_get_key( 1000 );
                if (key == KEY_ESC || key < 0){ 
					memset( buf, 0, count );		//clear sensitive data
					return -1;
                }
				else if( key == 0 )
					continue;
                else if (key == KEY_ENTER) {
                        if (count == 0) break;
                        if (count >= minlen) break;
                }
                else if (key == KEY_BS) {
                        if (count == 0) 
							continue;
                        count --;
                        ASC16(x, y, font_ept);
                        x -= 8;
                        ASC16(x, y, font_ept);
                }
                else if (key >= '0' && key <= '9') {
                        buf[count ++] = key;
                        if (show == 0)
                                read_sys_asc(key * 16, font_buf, 16);
                        ASC16(x, y, font_buf);
                        if (count == maxlen) {
                                ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);
                                break;
                        }
                        x += 8;
                }
        }
        buf[count] = 0;

        return count;
}


